package com.hp.bon.sgw.wh.channel.handler;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.Constants.MessageType;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.domain.MessageDetail;
import com.hp.bon.sgw.threads.MessageDetailCacheManager;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.bean.NetListQueryNewResponse;
import com.hp.ocs.diameter.message.AVP;
import com.hp.ocs.diameter.message.AVP_Grouped;
import com.hp.ocs.diameter.message.AVP_UTF8String;
import com.hp.ocs.diameter.message.AVP_Unsigned32;
import com.hp.ocs.diameter.message.AVP_Unsigned64;
import com.hp.ocs.diameter.message.Message;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * @ClassName: YHJQHandle
 * @Description: 用户鉴权
 * @author: zhoumengyi
 * @date 2019-07-16 18:03:00
 */
public class YHJQHandle implements IAsynCallHandler {
	private static final Logger _log = LoggerFactory.getLogger(YHJQHandle.class);

	private PrintStream printStream;
	private String qryType;
	private String wsURL;
	private String startDate;
	private String endDate;

	public YHJQHandle(PrintStream printStream, String qryType, String wsURL, String startDate, String endDate) {
		this.printStream = printStream;
		this.qryType = qryType;
		this.wsURL = wsURL;
		this.startDate = startDate;
		this.endDate = endDate;
	}

	@Override
	public int getProtocolType() {
		return 0;
	}

	@Override
	public void onCallResult(CallParam callParam) {
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(), _retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);// 11203
		} else {
			if (response instanceof Message) {// CCA -> XML
				ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
				ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			String respXML = convertResponseString((Message) response, callParam.getServiceResultCode());
			byte[] resp = respXML.getBytes("UTF-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
			if (callParam.getRetCode() == Constants.ResultCode.SUCCESS) {// 成功的消息，请求应答入库
				MessageDetail detail = new MessageDetail();
				detail.setBusinessCallId(callParam.getBussinessCallId());
				detail.setSessionId(callParam.getSessionId());
				detail.setServiceContextId(callParam.getServiceContextId());
				detail.setMessageType(MessageType.WSA);
				detail.setDetails(ack.getDATA());
				detail.setMsgTime(new Date(ack.getMsgTime()));
				detail.setOpType("send");
				detail.setHostId(callParam.getUserName());
				MessageDetailCacheManager.getInstance().add(detail);
			}
			TaskManager.taskProcess(callParam);
			_log.info("http response(cfq) " + respXML);
		} catch (UnsupportedEncodingException e) {
			_log.info("convertResponseString UnsupportedEncodingException error,msg=" + e.getMessage());
		} catch (IOException e) {
			_log.info("convertResponseString IOException,msg=" + e.getMessage());
		}
	}
	

	
	
	/**
	 * 返回最终json格式数据
	 * @param answer
	 * @param serviceResultCode
	 * @return
	 */
	private String convertResponseString(Message answer, int serviceResultCode) {
		_log.info("YHJQHandle serviceResultCode = {}", serviceResultCode);
		String response = "";
		Map<String, Object> data = new HashMap<String, Object>();
		Map<String, Object> map = getAvpsFromMessage(answer);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		if(map == null){
			// 解析下游返回数据出错
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
		}else if(serviceResultCode != 0){
			// 如果返回了错误码，则将错误信息转给用户
			if(1200 == serviceResultCode || 501 == serviceResultCode || 508 == serviceResultCode ){
				data.put("resultCode", "1003");
				data.put("resultMsg", "用户不存在");
			}else {
				data.put("resultCode", serviceResultCode);
				data.put("resultMsg", "查询失败");
			}
			
		}else{
			// 调用webservice接口查询详单信息
			// qryType：1语音类详单、2短信类详单、3数据类详单、4增值类详单
			// querytype = 57短信、58语音、59流量、60增值
			String querytype = "";
			if ("1".equals(qryType)) {
				querytype = "58";
			} else if ("2".equals(qryType)) {
				querytype = "57";
			} else if ("3".equals(qryType)) {
				querytype = "59";
			} else if ("4".equals(qryType)) {
				querytype = "60";
			}
			Map<String, Object> Data_Information = (Map<String, Object>) map.get("Data_Information");
			String buildStringMes = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ws=\"http://ws.hquery.ailk.com/\">"
					+ "<soapenv:Header/>"
					+ "<soapenv:Body>"
					+ "<ws:hquery>"
					+ "<param><![CDATA["
					+ "<query type='" + querytype + "' from='212'>"
					+ "<param name='acctId'></param>"
					+ "<param name='servid'>" + Data_Information.get("serv_id") + "</param>"
					+ "<param name='selectType'>0</param>"
					+ "<param name='beginDate'>" + startDate + "000000</param>"
					+ "<param name='endDate'>" + endDate + "235959</param>"
					+ "<param name='getFlag'>0</param>"
					+ "<param name='areaCode'>" + Data_Information.get("HomeAreaCode") + "</param>"
					+ "<start name='queryBatchStart'></start>"
					+ "<start name='queryBatch'></start>"
					+ "</query>]]>"
					+ "</param>"
					+ "</ws:hquery>"
					+ "</soapenv:Body>"
					+ "</soapenv:Envelope>";
			NetListQueryNewResponse netListQueryNewResponse = null;
			try{
				String resp = sendWebService(buildStringMes);
				XStream xstream2 = new XStream(new DomDriver());
				xstream2.alias("return", NetListQueryNewResponse.class);
				xstream2.autodetectAnnotations(true);
				netListQueryNewResponse = (NetListQueryNewResponse) xstream2.fromXML(resp.substring(resp.indexOf("<return>"), resp.indexOf("</ns1:hqueryResponse>")));
			}catch(Exception e){
				_log.error("详单webservice调用异常：", e);
			}
			String totalFee="0";
			if (netListQueryNewResponse != null) {
				//总费用以'分'为单位,下游参数乘以100
				Double totalFeeTemp=Double.valueOf(netListQueryNewResponse.getFluxInfo().split(",")[0])*100;
				Long round = Math.round(totalFeeTemp);
				totalFee=round.toString();
			}
			if (netListQueryNewResponse != null && "1".equals(qryType)) {
				//------------------------------- 语音 -------------------------------//
				List<Map<String, Object>> VoiceBillItems = new ArrayList<Map<String, Object>>();
				List<String> result = netListQueryNewResponse.getResultList();
				if (!CollectionUtils.isEmpty(result)) {
					for (String str : result) {
						Map<String, Object> resultMap = new HashMap<String, Object>();
						String[] strs = str.split(",");
						try {
							resultMap.put("beginTime", sdf.format(sdf.parse(strs[0])));
						} catch (ParseException e) {
							e.printStackTrace();
						}
						resultMap.put("callingArea", strs[1]);
						resultMap.put("callType", strs[2]);
						resultMap.put("calledNo", strs[3]);
						resultMap.put("duration", strs[5]);
						resultMap.put("callingType", strs[7]);
						resultMap.put("totalCharge", strs[9]);
						VoiceBillItems.add(resultMap);
					}
				}
				data.put("startDate", startDate);
				data.put("endDate", endDate);
				data.put("provinceCode", "027");
				data.put("qryType", qryType);
				data.put("voiceBillItem", VoiceBillItems);
				data.put("totalRecord", netListQueryNewResponse.getTotalSize());
				data.put("totalFee", totalFee);
				data.put("totalVolume", netListQueryNewResponse.getFluxInfo().split(",")[2]);
				data.put("resultCode", "0");
				data.put("resultMsg", "SUCCESS");
			} else if (netListQueryNewResponse != null && "2".equals(qryType)) {
				//------------------------------- 短信 -------------------------------//
				List<Map<String, Object>> SmsBillItems = new ArrayList<Map<String, Object>>();
				List<String> result = netListQueryNewResponse.getResultList();
				if (!CollectionUtils.isEmpty(result)) {
					for (String str : result) {
						Map<String, Object> resultMap = new HashMap<String, Object>();
						String[] strs = str.split(",");
						try {
							resultMap.put("startTime", sdf.format(sdf.parse(strs[0])));
						} catch (ParseException e) {
							e.printStackTrace();
						}
						resultMap.put("calledNo", strs[1]);
						resultMap.put("callType", strs[2]);
						resultMap.put("fee", strs[3]);
						SmsBillItems.add(resultMap);
					}
				}
				data.put("startDate", startDate);
				data.put("endDate", endDate);
				data.put("provinceCode", "027");
				data.put("qryType", qryType);
				data.put("smsBillItem", SmsBillItems);
				data.put("totalRecord", netListQueryNewResponse.getTotalSize());
				data.put("totalFee", totalFee);
				data.put("totalVolume", netListQueryNewResponse.getFluxInfo().split(",")[2]);
				data.put("resultCode", "0");
				data.put("resultMsg", "SUCCESS");

			} else if (netListQueryNewResponse != null && "3".equals(qryType)) {
				//------------------------------- 上网 -------------------------------//
				List<Map<String, Object>> DataBillItems = new ArrayList<Map<String, Object>>();
				List<String> result = netListQueryNewResponse.getResultList();
				if (!CollectionUtils.isEmpty(result)) {
					for (String str : result) {
						Map<String, Object> resultMap = new HashMap<String, Object>();
						String[] strs = str.split(",");
						try {
							resultMap.put("startTime", sdf.format(sdf.parse(strs[0])));
						} catch (ParseException e) {
							e.printStackTrace();
						}
						resultMap.put("callingArea", strs[1]);
						resultMap.put("listType", strs[2]);
						resultMap.put("duration", strs[3]);
						resultMap.put("volume", strs[4]);
						resultMap.put("businessType", strs[5]);
						resultMap.put("fee", strs[6]);
						DataBillItems.add(resultMap);
					}
				}
				data.put("startDate", startDate);
				data.put("endDate", endDate);
				data.put("provinceCode", "027");
				data.put("qryType", qryType);
				data.put("dataBillItem", DataBillItems);
				data.put("totalRecord", netListQueryNewResponse.getTotalSize());
				data.put("totalFee", totalFee);
				data.put("totalVolume", netListQueryNewResponse.getFluxInfo().split(",")[2]);
				data.put("resultCode", "0");
				data.put("resultMsg", "SUCCESS");
			} else if (netListQueryNewResponse != null && "4".equals(qryType)) {
				//------------------------------- 增值 -------------------------------//
				List<Map<String, Object>> IncrBillItems = new ArrayList<Map<String, Object>>();
				List<String> result = netListQueryNewResponse.getResultList();
				if (!CollectionUtils.isEmpty(result)) {
					for (String str : result) {
						Map<String, Object> resultMap = new HashMap<String, Object>();
						String[] strs = str.split(",");
						try {
							resultMap.put("startTime", sdf.format(sdf.parse(strs[0])));
						} catch (ParseException e) {
							e.printStackTrace();
						}
						resultMap.put("spCode", strs[2]);
						resultMap.put("businessType", strs[4]);
						resultMap.put("feeType", strs[5]);
						resultMap.put("businessInfo", strs[6]);
						resultMap.put("fee ", strs[7]);
						IncrBillItems.add(resultMap);
					}
				}
				data.put("startDate", startDate);
				data.put("endDate", endDate);
				data.put("provinceCode", "027");
				data.put("qryType", qryType);
				data.put("incrBillItem", IncrBillItems);
				data.put("totalRecord", netListQueryNewResponse.getTotalSize());
				data.put("totalFee", totalFee);
				data.put("totalVolume", netListQueryNewResponse.getFluxInfo().split(",")[2]);
				data.put("resultCode", "0");
				data.put("resultMsg", "SUCCESS");
			}else{
				// 调用webservice接口失败
				data.put("resultCode", "-1");
				data.put("resultMsg", "查询失败");
			}
		}
		Gson gson = new Gson();
		response = gson.toJson(data);
		return response;
	}

	
	/**
	 * 处理CCA结果
	 * @param answer
	 * @return
	 */
	public Map<String, Object> getAvpsFromMessage(Message answer) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			AVP avp = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP);
			AVP_Grouped avpServiceInfomation = new AVP_Grouped(avp);
			AVP[] avps = avpServiceInfomation.queryAVPs();
			for (AVP avpData : avps) {
				
				if (avpData.code() == 20631 && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("Result", String.valueOf(new AVP_Unsigned32(avpData).queryValue()));
				}

				if (avpData.code() == 80400 && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					Map<String, Object> DataInformationMap = new HashMap<String, Object>();
					AVP_Grouped avpDataInformation = new AVP_Grouped(avpData);

					// 客户名称
					AVP CustName = avpDataInformation.find(80416, Constants.DIAMETER_VENDOR_CT);
					if (CustName != null) {
						DataInformationMap.put("CustName", new AVP_UTF8String(CustName).queryValue());
					}

					// 用户标识
					AVP Serv_Id = avpDataInformation.find(90020, Constants.DIAMETER_VENDOR_CT);
					if (Serv_Id != null) {
						DataInformationMap.put("serv_id", String.valueOf(new AVP_Unsigned64(Serv_Id).queryValue()));
					}

					// 产品标识
					AVP ProductId = avpDataInformation.find(82022, Constants.DIAMETER_VENDOR_CT);
					if (ProductId != null) {
						DataInformationMap.put("ProductId", String.valueOf(new AVP_Unsigned32(ProductId).queryValue()));
					}

					// 产品名称
					AVP ProductName = avpDataInformation.find(80434, Constants.DIAMETER_VENDOR_CT);
					if (ProductName != null) {
						DataInformationMap.put("ProductName", new AVP_UTF8String(ProductName).queryValue());
					}

					// 本地网区号
					AVP HomeAreaCode = avpDataInformation.find(80615, Constants.DIAMETER_VENDOR_CT);
					if (HomeAreaCode != null) {
						DataInformationMap.put("HomeAreaCode", String.valueOf(new AVP_Unsigned32(HomeAreaCode).queryValue()));
					}

					// 用户状态：0正常、1停机、 3拆机、5.其他异常资料(归档, 作废)
					AVP ServState = avpDataInformation.find(80423, Constants.DIAMETER_VENDOR_CT);
					if (ServState != null) {
						DataInformationMap.put("ServState", String.valueOf(new AVP_Unsigned32(ServState).queryValue()));
					}

					// 状态时间
					AVP StateDate = avpDataInformation.find(80419, Constants.DIAMETER_VENDOR_CT);
					if (StateDate != null) {
						DataInformationMap.put("StateDate", new AVP_UTF8String(StateDate).queryValue());
					}

					// 付费方式：0后付费、1预付费
					AVP PaymentFlag = avpDataInformation.find(82023, Constants.DIAMETER_VENDOR_CT);
					if (PaymentFlag != null) {
						DataInformationMap.put("PaymentFlag", String.valueOf(new AVP_Unsigned32(PaymentFlag).queryValue()));
					}

					// 用户属性：0拥有集团帐户、1没有集团帐户
					AVP GroupUser = avpDataInformation.find(82067, Constants.DIAMETER_VENDOR_CT);
					if (GroupUser != null) {
						DataInformationMap.put("GroupUser", String.valueOf(new AVP_Unsigned32(GroupUser).queryValue()));
					}
					map.put("Data_Information", DataInformationMap);
				}
			}
		} catch (Exception e) {
			map = null;
			_log.info("getAvpsFromMessage Exception error,msg=" + e.getMessage());
		}
		return map;
	}

	
	/**
	 * 调用详单查询webservice接口
	 * @param param
	 * @return
	 */
	private String sendWebService(String param) {
		int timeOut = 5000;
		String resp = "";
		PostMethod post = new PostMethod(wsURL);
		try {
			RequestEntity requestEntity = new StringRequestEntity(param, "text/xml", "UTF-8");
			post.setRequestEntity(requestEntity);
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5 * 1000);
			client.getHttpConnectionManager().getParams().setSoTimeout(timeOut);
			try {
				client.executeMethod(post);
			} catch (HttpException e) {
				_log.info("===========webservice call timeout===============" + wsURL);
				e.printStackTrace();
			} catch (IOException e) {

				return "";
			}
			try {
				_log.info("===========完成webservice===============" + resp);
				resp = post.getResponseBodyAsString();
			} catch (IOException e) {
				_log.info("===========webservice call timeout===============" + wsURL);
				return "";
			}
		} catch (UnsupportedEncodingException e) {
			_log.info("===========webservice call timeout===============" + wsURL);
			e.printStackTrace();
		}
		return resp;
	}
	
}
